<?php

namespace App\Http\Services\Api\V1\App\Customer;

use App\Models\Customers\TwitterUser;
use App\Models\Setting;
use App\Services\Utils\ApiChecker;
use Laravel\Socialite\One\TwitterProvider;
use \League\OAuth1\Client\Server\Twitter;

class TwitterService extends TwitterProvider
{
    use ApiChecker;

    const OAUTH_TYPE_TWITTER_APP = 'twitter_app';
    const OAUTH_TYPE_TWITTER_PC = 'twitter_pc';
    const KEY_OAUTH_TWITTER_APP_APP_ID = 'oauth_twitter_app_app_id';
    const KEY_OAUTH_TWITTER_PC_APP_ID = 'oauth_twitter_pc_app_id';
    const KEY_OAUTH_TWITTER_APP_APP_SECRET = 'oauth_twitter_app_app_secret';
    const KEY_OAUTH_TWITTER_PC_APP_SECRET = 'oauth_twitter_pc_app_secret';
    const PC_REDIRECT_URL = '%s/index.php?route=account/login/oauthCallback&type=%s';

    /**
     * TwitterService constructor.
     * @param $type
     */
    public function __construct($type)
    {
        $config = $this->getConfig($type);

        /** @var Twitter $twitter_server */
        $twitter_server = new Twitter($config);
        $request = request();

        parent::__construct($request, $twitter_server);
    }

    /**
     * @param $type
     * @return array
     */
    public function getConfig($type)
    {
        if ($type === self::OAUTH_TYPE_TWITTER_PC) {

            $clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_TWITTER_PC_APP_ID);
            $clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_TWITTER_PC_APP_SECRET);
            $redirectUrl = route('pc_oauth_callback', self::OAUTH_TYPE_TWITTER_PC);
        } else {

            $clientId = Setting::getSettingSpecifyValue(self::KEY_OAUTH_TWITTER_APP_APP_ID);
            $clientSecret = Setting::getSettingSpecifyValue(self::KEY_OAUTH_TWITTER_APP_APP_SECRET);
            $redirectUrl = '';
        }

        return $config = ['identifier'    => $clientId,
                          'secret'        => $clientSecret,
                          'callback_uri'  => $redirectUrl,
                          'client_id'     => $clientId,
                          'client_secret' => $clientSecret,
                          'redirect'      => $redirectUrl,
        ];
    }

    /**
     * app端处理twitter第三方登录，获取twitter用户的信息
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|null|object
     * @throws \Exception
     */
    public function handleTwitterCallback()
    {
        // laravel/socialite 请求的认证
        session(['state' => 890]);
        request()->offsetSet('state', 890);

        $user = $this->createOrUpdateUser(self::OAUTH_TYPE_TWITTER_APP);

        return $user;
    }

    /**
     * pc端处理twitter第三方登录，获取配置信息
     * @return mixed
     */
    public function generateTwitterProvider()
    {
        return $this;
    }

    /**
     * pc端处理twitter第三方登录，获取twitter用户的信息
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|null|object
     * @throws \Exception
     */
    public function twitterCallback()
    {
        $user = $this->createOrUpdateUser(self::OAUTH_TYPE_TWITTER_PC);

        $data = http_build_query([
            'customer_id'   => $user->customer_id ?? '',
            'token'         => $user->jwt_token ?? '',
            'type'          => self::OAUTH_TYPE_TWITTER_PC,
            'oauth_user_id' => $user['oauth_user_id'] ?? '',
        ]);

        return redirect(sprintf(self::PC_REDIRECT_URL, config('app.web-url'), self::OAUTH_TYPE_TWITTER_PC.'&'.$data));
    }

    /**
     * @param $oauth_type
     * @return \App\Models\Customers\Customer|array|\Illuminate\Database\Eloquent\Model|\Laravel\Socialite\One\User|null|object
     * @throws \Exception
     */
    private function createOrUpdateUser($oauth_type)
    {
        try {
            /** @var \Laravel\Socialite\One\User $user */
            $user =  $this->user();
        } catch (\Exception $e){
            logger($e->getMessage());
            $this->checkIsTrue(false, trans('customer.twitter_oauth_error'));
        }

        $twitter_data = $this->assembleTwitterUser($user);
        $twitter_user = $this->updateOrCreateUser($twitter_data);

        $user = (new ThirdPartyService)->generateUser($twitter_user, $oauth_type);

        return $user;
    }

    /**
     * @see MockData::getTwitterUser();
     *
     * @param \Laravel\Socialite\One\User $user
     * @return array
     */
    public function assembleTwitterUser(\Laravel\Socialite\One\User $user)
    {
        $twitter_user_data = [
            'id'              => $user->id ?? '',
            'nickname'        => $user->nickname ?? '',
            'name'            => $user->name ?? '',
            'email'           => $user->email ?? '',
            'avatar'          => $user->avatar ?? '',
            'avatar_original' => $user->avatar_original ?? '',
        ];

        return $twitter_user_data;

    }

    /**
     * @param array $twitter_user_data
     * @return TwitterUser
     */
    public function updateOrCreateUser(array $twitter_user_data)
    {
        /** @var TwitterUser $twitter_user */
        $twitter_user = (new TwitterUser)->updateOrCreate (
            ['id' => $twitter_user_data['id']], $twitter_user_data
        );

        return $twitter_user;
    }
}